package example.runner3;
import java.util.HashSet;
import java.util.Set;

import service.network.NetworkCalculationService;
import materials.network.NetworkInterface;
import materials.result.NetworkResultInterface;

/**
 * Rennt durch das Feld und soll so viel essen wie möglich
 * @author Ramox
 *
 */
public class Runner
{
	private double _health; //Anzahl der gefutterten Essen
	private NetworkInterface _netz;
	private double[] _lastOut;
	
	/**
	 * Erzeugt einen Runner mit dem Netz netz
	 * @param netz Netz des Runners
	 */
	public Runner(NetworkInterface netz)
	{
		_health = 0;
		_netz = netz;
		_lastOut = new double[8];
		for(int i = 0; i < 8; i++){
			_lastOut[i] = 0;
		}
	}
	
	
	

	/**
	 * gibt das netz zurück
	 * 
	 * @return netz des runners
	 */
	public NetworkInterface getNet()
	{
		return _netz;
	}

	/**
	 * gibt die Fitness des Runners aus
	 * 
	 * @return Fitness des Runners
	 */
	public double getFitness()
	{
		return _health;
	}

	/**
	 * Berechnet die Richtung in der der Runner seinen nächsten schritt machen will.
	 * 
	 * @param umgebung umgebung um den Runner (5x5)
	 * 
	 * @return Richtung in die der Runner gehen will
	 */
	public Direction getNextDirection(int[] umgebung)
	{
		NetworkCalculationService ncs = new NetworkCalculationService(_netz);
		double[] ndim = new double[33];

		
		//input für das netz
		for (int i = 0; i < 25; i++)
		{
			if (umgebung[i] == -2) //essen
			{
				ndim[i] = 10;
			}
			else if (umgebung[i] == 0) //leer
			{
				ndim[i] = 0;
			}
			else //wand und andere runner
			{
				ndim[i] = -4;
			}
		}
		for (int i=25;i<33;i++){
			ndim[i]=_lastOut[i-25]-0.5;
		}

		double[] nri = ncs.calculateInput(ndim);

		_lastOut = nri;
		
		//berechnung der Ausgabe (51-58 sind die Neuronen in Layer 3)
		double max = nri[0];
		int maxId = 0;
		for (int i = 0; i < 8; i++)
		{
			if (nri[i] > max)
			{
				maxId = i;
				max = nri[i];
			}
		}
		
		//Richtung des Neuronen mit der größten Ausgabe ist die gewünschte
		return Direction.values()[maxId];
	}

	/**
	 * erhöht die Anzahl der Essen
	 */
	public void increaseHealth()
	{
		_health++;
	}

	/**
	 * erniedrigt die anzahl der Essen, wenn ein runner gegen die Wand läuft z.b.
	 */
	public void decreaseHealth()
	{
		//_health -= Math.pow(Math.random(),10); 
	}

	/**
	 * gibt die Anzahl der essen zurück
	 * 
	 * @return Anzahl der essen
	 */
	public double getHealth()
	{
		return _health;
	}

}
